#include "NWNXManager.h"
#include "tool_include/planning/heuristics/Heuristic.hxx"
#include "tool_include/planning/heuristics/Max_Heuristic.hxx"


NWNXManager::NWNXManager(){
    char _config[] = "nwnxplanner.ini";
    readFile(_config);
    
    iCursor = 0;
    
}

NWNXManager::~NWNXManager(){
    
}


void NWNXManager::readFile(char* _filename){
    std::ifstream _configFile;
    _configFile.open(_filename);
    
     if(_configFile.is_open()){
        std::cout<<"NWNX_Planner reading configuration ..."<<std::endl;
        getline(_configFile, domain_file);
        getline(_configFile, instance_file);
    }else{
         std::cout<<"NWNX_Planne could not open configuration ..."<<std::endl;
    }

    std::cout<<"PDDL Domain:"<<domain_file<<std::endl;
    std::cout<<"PDDL Problem:"<<instance_file<<std::endl;
    
    _configFile.close();
    
}

void NWNXManager::loadPDDL(){
    
    this->adl_compiler.get_problem_description(this->domain_file, this->instance_file, this->strips_prob, true);
    std::cout << std::endl;
    std::cout << "Actions: " << strips_prob.num_actions()<<" ";
    std::cout << "Fluents: " << strips_prob.num_fluents() << std::endl;
    
}

void NWNXManager::buildPlan(){
    
    this->estimator.initialize(this->strips_prob);
    this->estimator.compute(this->strips_prob.init());
    
    aig_tk::Cost_Type goal_cost = this->estimator.eval( this->strips_prob.goal()  );
    std::cout<<"Goal Distance is "<<goal_cost<<std::endl;
    
    aig_tk::Node* n0 = aig_tk::Node::root( this->strips_prob );
    aig_tk::Propagator< aig_tk::Max_Heuristic > rel_plan( this->strips_prob );
    rel_plan.build_propagation_graph( n0 );
    
    aig_tk::Relaxed_Plan_Extractor< aig_tk::Max_Heuristic > h_ff;
    h_ff.initialize( this->strips_prob );
    unsigned  cost_rel_plan = h_ff.eval( this->strips_prob.init(), this->strips_prob.goal() );
	
    std::cout<<std::endl<<"Cost of Relaxed Plan: "<< cost_rel_plan << std::endl;
    
    
    
    this->engine.set_heuristic(this->estimator);
    this->engine.set_problem(this->strips_prob);
    
    float t0, tf;
    t0 = time_used();
    
    if( this->engine.solve(n0, this->plan) ){
	tf = time_used();
        report_interval(t0, tf, std::cout);
	//printPlan(t0, tf);
    }

}

void NWNXManager::printPlan(float t0, float tf){
        
        aig_tk::Cost_Type plan_cost = 0;

        std::cout << std::endl;
	std::cout << "================================================"<<std::endl;                                 
	std::cout << ";; SOLUTION " <<std::endl;
	std::cout << ";;\t Plan cost: " << std::fixed << plan_cost << ", steps: " << this->plan.size() << std::endl;
	std::cout << ";;\t Time: ";
	report_interval(t0, tf, std::cout);
	std::cout << std::endl<<"================================================"<<std::endl;                  

	for ( unsigned k = 0; k < this->plan.size(); k++ )
	{
		aig_tk::Action* a = this->plan[k]->op(); 
		std::cout<< a->name()<<""<< a->signature()<<std::endl;
		plan_cost = aig_tk::add( plan_cost, a->cost() );
	}
    
}
        
std::string NWNXManager::getNextAction(){
    
    std::string sAction;
    
    if(iCursor<this->plan.size()){
        aig_tk::Action* a = this->plan[iCursor]->op();
        sAction = a->signature();
        int _size = sAction.size();
        sAction.erase(0, 1);
        sAction.erase(_size-2, 1);
        iCursor++;
    }else{
        sAction = "END_OF_PLAN";
    }
    
    return sAction;
}